package com.ta.httplib.interceptor;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.Map;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import com.ta.httplib.utils.LogUtils;
import com.ta.httplib.utils.StringUtils;

/**
 * 请求日志
 */
public abstract class HttpLogInterceptor implements Interceptor {

    @NotNull
    @Override
    public Response intercept(Chain chain) throws IOException {
        long t1 = System.currentTimeMillis();

        Request original = chain.request();

        String body = bodyToString(original.body());

        Request.Builder reqBuilder = original.newBuilder();
        Map<String, String> headers = getHeaders();
        for (String key : headers.keySet()) {
            reqBuilder.addHeader(key, headers.get(key));
        }
        Request request = reqBuilder.method(original.method(), original.body()).build();

        LogUtils.logE(String.format("╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════\n" +
                        "║ " + getClass().getName() + ".intercept(Chain chain) \n" +
                        "║ 请求发起 \n" +
                        "╟──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" +
                        "║ request method  : %s\n" +
                        "║ request url     : %s\n" +
                        "║ request body    : %s\n" +
                        "║ request headers : %s\n" +
                        "╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════"
                , request.method(),
                request.url().toString(),
                body,
                request.headers().toString().replaceAll("\\n", "\\\n║                   ")));

        Response response = chain.proceed(request);

        long t2 = System.currentTimeMillis();
        ResponseBody responseBody = response.peekBody(1024 * 1024);
        String responseBodyStr = responseBody.string().replaceAll("\\n", "");
        LogUtils.logE(String.format("╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════\n" +
                        "║ " + getClass().getName() + ".intercept(Chain chain) \n" +
                        "║ 请求响应 \n" +
                        "╟──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" +
                        "║ 耗时 (不准)       : %s 毫秒\n" +
                        "║ response url     : %s\n" +
                        "║ response body    : %s\n" +
                        "║ response headers : %s\n" +
                        "╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════",
                String.valueOf(t2 - t1),
                response.request().url(),
                StringUtils.unicodeToString(formatJson(responseBodyStr)),
                response.headers().toString().replaceAll("\\n", "\\\n║                   ")));
        return response;
    }

    private static String bodyToString(final RequestBody request) {
        try {
            final RequestBody copy = request;
            if (copy == null) {
                return "";
            }
            final Buffer buffer = new Buffer();
            copy.writeTo(buffer);
            return buffer.readUtf8();
        } catch (final IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 格式化json
     */
    private String formatJson(String jsonStr) {
        if (null == jsonStr || "".equals(jsonStr)) return "";
        StringBuilder sb = new StringBuilder();
        char last;
        char current = '\0';
        int indent = 0;
        for (int i = 0; i < jsonStr.length(); i++) {
            last = current;
            current = jsonStr.charAt(i);
            //遇到{ [换行，且下一行缩进
            switch (current) {
                case '{':
                case '[':
                    sb.append(current);
                    sb.append('\n');
                    indent++;
                    addIndentBlank(sb, indent);
                    break;

                //遇到} ]换行，当前行缩进
                case '}':
                case ']':
                    sb.append('\n');
                    indent--;
                    addIndentBlank(sb, indent);
                    sb.append(current);
                    break;
                //遇到,换行
                case ',':
                    sb.append(current);
                    if (last != '\\') {
                        sb.append('\n');
                        addIndentBlank(sb, indent);
                    }
                    break;
                default:
                    sb.append(current);
            }
        }
        return sb.toString();
    }

    /**
     * 添加space
     */
    private void addIndentBlank(StringBuilder sb, int indent) {
        for (int i = 0; i < indent; i++) {
            sb.append('\t');
        }
    }

    public abstract Map<String, String> getHeaders();
}